package com.dyson.pool;

import lombok.ToString;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据源连接池
 *
 * @author:DysonWy@Gmail.com
 * @time:2019/8/10 12:21
 */
@ToString
public class DbPool extends AbstractDbPool {
    //空闲连接
    private final List<ConnectionPool> idelConnections = new ArrayList<>();
    //激活连接(正在使用连接)
    private final List<ConnectionPool> activeConnections = new ArrayList<>();
    //线程锁对象
    private final Object monitor = new Object();
    //最大激活连接数
    private int maxActiveConnection = 10;
    //最大空闲连接
    private int maxIdelConnection = 5;
    //获取连接最大等待时间(单位:mill)
    private int waitTime = 20000;

    /**
     * 覆盖父类获取连接方法
     *
     * @return
     * @throws SQLException
     */
    @Override
    public Connection getConnection() throws SQLException {
        //从连接池获取
        return popConnection(super.getUsername(), super.getPassword()).getRealConnection();
    }

    /**
     * 释放激活连接到空闲连接
     * 需要拦截调用者connection.close()
     *
     * @param connectionPool
     */
    public void closeConnection(ConnectionPool connectionPool) {
        //避免线程问题
        synchronized (monitor) {
            //减少激活连接数,改变为空闲连接
            activeConnections.remove(connectionPool);
            //判断是否为空闲连接最大值
            if (idelConnections.size() < maxIdelConnection) {
                //存入空闲连接
                idelConnections.add(connectionPool);
            }
            //唤醒线程有空闲连接,避免多余等待
            monitor.notifyAll();
        }
    }


    /**
     * 从连接池获取连接
     *
     * @param username
     * @param password
     * @return
     */
    private ConnectionPool popConnection(String username, String password) throws SQLException {
        //连接对象
        ConnectionPool connectionPool = null;
        //循环获取连接
        while (connectionPool == null) {
            //避免线程问题
            synchronized (monitor) {
                //验证空闲连接不为空
                if (!idelConnections.isEmpty()) {
                    //从0开始清除连接并返回
                    connectionPool = idelConnections.remove(0);
                } else {
                    //无空闲连接,判断是否达到最大连接数
                    if (activeConnections.size() < maxActiveConnection) {
                        //创建连接,并存入激活连接池
                        connectionPool = new ConnectionPool(super.getConnection(), this);
                        activeConnections.add(connectionPool);
                    }
                }
                //无空闲连接且已达连接最大数,进行等待
                if (connectionPool == null) {
                    try {
                        //注意已有空闲连接进行唤醒,避免多余等待
                        monitor.wait(waitTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }

            }
        }
        return connectionPool;
    }

}
